package org.jaaksi.customviewdemo.view

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import extension.dp

/**
 *  可选择线条粗细，颜色，支持橡皮擦功能，清空功能
 *  橡皮擦模式，应该显示一个橡皮擦
 */
class PaintView(context: Context, attrs: AttributeSet?) : View(context, attrs) {

    private var lastX = 0f
    private var lastY = 0f
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG)

    // 是否是橡皮擦模式
    private var isEraserMode = false

    // 保存的path列表
    private var pathList = mutableListOf<PathInfo>()

    // 撤回的path列表
    private var revokePathList = mutableListOf<PathInfo>()
    private var path = Path()
    var strokeWith = 3.dp
    var color = Color.BLACK
    private val clearMode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)

    init {
        paint.apply {
            style = Paint.Style.STROKE
            // 指定画笔的开始结束描边处理，圆角是固定的，线宽的一半
            strokeCap = Paint.Cap.ROUND
            // 指定画笔的连接处的描边处理
            strokeJoin = Paint.Join.MITER
            isAntiAlias = true
            strokeWidth = this@PaintView.strokeWith
            color = this@PaintView.color
        }
        // 关闭硬件加速
        setLayerType(LAYER_TYPE_SOFTWARE, null)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                path.moveTo(event.x, event.y)
                lastX = event.x
                lastY = event.y
            }
            MotionEvent.ACTION_MOVE -> {
                // 使用贝塞尔曲线
                path.quadTo(lastX, lastY, event.x, event.y)
                invalidate()
                lastX = event.x
                lastY = event.y
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                pathList.add(
                    PathInfo(Path(path), Paint(paint))
                )
                path.reset()
            }
        }
        return true
    }

    // 撤销
    fun undo() {
        if (pathList.isEmpty()) return
        val path = pathList.removeAt(pathList.lastIndex)
        revokePathList.add(path)
        invalidate()
    }

    // 反撤销
    fun redo() {
        if (revokePathList.isEmpty()) return
        val path = revokePathList.removeAt(revokePathList.lastIndex)
        pathList.add(path)
        invalidate()
    }

    /**
     * @param isEraserMode 是否是橡皮擦模式
     */
    fun setMode(isEraserMode: Boolean) {
        this.isEraserMode = isEraserMode
    }

    override fun onDraw(canvas: Canvas) {
        // 绘制保存的path
        pathList.forEach {
            drawPath(canvas, it)
        }
        // 绘制当前path
        drawPath(canvas)
    }

    private fun drawPath(canvas: Canvas, pathInfo: PathInfo) {
        pathInfo.paint.apply {
            paint.strokeWidth = strokeWidth
            paint.color = color
            paint.xfermode = xfermode
        }

        canvas.drawPath(pathInfo.path, paint)
    }

    private fun drawPath(canvas: Canvas) {
        if (isEraserMode) {
            paint.xfermode = clearMode
        } else {
            // 绘制当前的path
            paint.xfermode = null
            paint.color = color
        }
        paint.strokeWidth = strokeWith
        canvas.drawPath(path, paint)
    }
}

data class PathInfo(val path: Path, val paint: Paint)